#include "app_serial.h"

int app_serial_init(device_t *device)
{
    app_serial_setRaw(device);
    app_serial_setBraudRate(device, BR_9600);
    app_serial_setParity(device, Parity_NONE);
    app_serial_setStopBits(device, StopBits_1);

    // 刷新串口，让设置生效
    int result = tcflush(device->fd, TCIOFLUSH);
    if (result != 0)
    {
        log_error("串口初始化设置失败");
        return -1;
    }

    log_debug("串口初始化设置成功");
    return 0;
}
/**
 * 设置波特率
 */
int app_serial_setBraudRate(device_t *device, BraudRate rate)
{
    struct termios attr;
    if (tcgetattr(device->fd, &attr) != 0)
    {
        log_error("tcgetattr failed");
        return -1;
    }
    // 设置波特率
    cfsetispeed(&attr, rate);
    cfsetospeed(&attr, rate);
    // 设置串口属性(指定暂不生效，调用刷新才生效)
    if (tcsetattr(device->fd, TCSAFLUSH, &attr) != 0)
    {
        log_error("tcsetattr error");
        return -1;
    }
    return 0;
}

/**
 * 设置校验位
 */
int app_serial_setParity(device_t *device, Parity parity)
{
    struct termios attr;

    if (tcgetattr(device->fd, &attr) != 0)
    {
        log_error("tcgetattr failed");
        return -1;
    }
    // 设置校验位
    attr.c_cflag &= ~(PARENB | PARODD); // 清除校验位
    attr.c_cflag |= parity;             // 设置校验位
    // 设置串口属性(指定暂不生效，调用刷新才生效)
    if (tcsetattr(device->fd, TCSAFLUSH, &attr) != 0)
    {
        log_error("tcsetattr error");
        return -1;
    }
    return 0;
}

/**
 * 设置停止位
 */
int app_serial_setStopBits(device_t *device, StopBits stopBits)
{
    struct termios attr;
    if (tcgetattr(device->fd, &attr) != 0)
    {
        log_error("tcgetattr failed");
        return -1;
    }
    // 设置停止位
    attr.c_cflag &= ~CSTOPB;  // 清除停止位
    attr.c_cflag |= stopBits; // 设置停止位
    // 设置串口属性(指定暂不生效，调用刷新才生效)
    if (tcsetattr(device->fd, TCSAFLUSH, &attr) != 0)
    {
        log_error("tcsetattr error");
        return -1;
    }
    return 0;
}

/**
 * 设置是否阻塞模式
 */
int app_serial_setBlock(device_t *device, int is_block)
{
    struct termios attr;
    if (tcgetattr(device->fd, &attr) != 0)
    {
        log_error("tcgetattr failed");
        return -1;
    }
    // 修改属性（是否阻塞）
    if (is_block == 1)
    {
        attr.c_cc[VMIN] = 1;  // 至少读取一个字节
        attr.c_cc[VTIME] = 0; // 没有数据会一直等待
    }
    else
    {
        attr.c_cc[VMIN] = 0;  // 最少读取0个字节
        attr.c_cc[VTIME] = 2; // 没有数据会等待2*100ms
    }
    // 设置串口属性(指定暂不生效，调用刷新才生效)
    if (tcsetattr(device->fd, TCSAFLUSH, &attr)!= 0)
    {
        log_error("tcsetattr error");
        return -1;
    }
    return 0;
}

/**
 * 设置为原始模式
 */
int app_serial_setRaw(device_t *device)
{
    struct termios attr;
    if (tcgetattr(device->fd, &attr) != 0)
    {
        log_error("tcgetattr failed");
        return -1;
    }
    // 设置原始模式
    cfmakeraw(&attr);
    // 设置串口属性(指定暂不生效，调用刷新才生效)
    if (tcsetattr(device->fd, TCSAFLUSH, &attr) != 0)
    {
        log_error("tcsetattr error");
        return -1;
    }

    return 0;
}